跳到主要内容

Go 的 exec 包-执行命令

执行命令并获得输出结果

func main() {
cmd := exec.Command("ls", "-lah")
out, err := cmd.CombinedOutput()
if err != nil {
log.Fatalf("cmd.Run() failed with %s\n", err)
}
fmt.Printf("combined out:\n%s\n", string(out))
}

将 stdout 和 stderr 分别处理

func main() {
cmd := exec.Command("ls", "-lah")
var stdout, stderr bytes.Buffer
cmd.Stdout = &stdout
cmd.Stderr = &stderr
err := cmd.Run()
if err != nil {
log.Fatalf("cmd.Run() failed with %s\n", err)
}
outStr, errStr := string(stdout.Bytes()), string(stderr.Bytes())
fmt.Printf("out:\n%s\nerr:\n%s\n", outStr, errStr)
}

配置环境变量

改变执行程序的环境(environment)

cmd := exec.Command("programToExecute")
additionalEnv := "FOO=bar"
newEnv := append(os.Environ(), additionalEnv)
cmd.Env = newEnv
out, err := cmd.CombinedOutput()
if err != nil {
log.Fatalf("cmd.Run() failed with %s\n", err)
}
fmt.Printf("%s", out)

预先检查程序是否存在

可以调用 exec.LookPath 方法来检查:

func checkLsExists() {
path, err := exec.LookPath("ls")
if err != nil {
fmt.Printf("didn't find 'ls' executable\n")
} else {
fmt.Printf("'ls' executable is in '%s'\n", path)
}
}

或者直接使用 os.Stat("appName")

检查开了几个子进程

利用进程名获取进程号(以自己创建的进程 middlebaby 为例)

ps -ef|grep middlebaby|grep -v "grep"|awk '{print $2}'

grep 的输出都会有 grep 自身这个进程在,用 grep -v "grep" 可以把这一行干掉,然后 awk '{print $2}' 就是打印第二列数字,即 16154 (这里因为是通过 makefile 启动的,所以有两个进程)

awk 是处理文本文件的一个应用程序,几乎所有 Linux 系统都自带这个程序。它依次处理文件的每一行,并读取里面的每一个字段。对于日志、CSV 那样的每行格式相同的文本文件,awk 可能是最方便的工具。

使用 pgrep 命令检查子进程

pgrep -P $parent_pid

pgrep 允许你基于给定条件来查找正在运行的程序的进程 ID。它可以是进程名字的全称或者一部分,进程运行者,或者其他属性。

或者使用 ps 的 ppid flag

ps --ppid $parent_pid

References

linux查看进程所有子进程和线程